#pragma once

#include <iostream>
#include <unordered_map>
#include <memory>
#include "Connection.hpp"
#include "Epoller.hpp"

// 反应堆，可以理解为TcpServer
class Reactor
{
    static const int gnum = 64;

public:
    Reactor() : _epoller(std::make_unique<Epoller>()), _isRunning(false)
    {
    }

    ~Reactor()
    {
    }

    void AddConnection(int fd, uint32_t event, InetAddr &addr, int type)
    {
        // 1.构建connection
        Connection *newcon = new Connection(fd);
        newcon->SetEvent(event);
        newcon->SetAddr(addr);
        newcon->SetType(type);
        newcon->SetReactor(this);

        if (type == ListenSock)
            newcon->HandlerRegister(_OnConnect, nullptr, nullptr);
        else
            newcon->HandlerRegister(_OnReceiver, _OnSender, _OnExcepter);

        // 2. 将fd和event交给内核的 epoll 模型管理
        if (_epoller->AddEvent(fd, event) < 0)
            return;

        // 3. 将连接交给_connections
        _connections.insert(std::make_pair(fd, newcon));
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, gnum, timeout);
        for (int i = 0; i < n; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;

            // 异常统一交给一个地方处理
            if (revents & EPOLLERR)
                revents |= (EPOLLIN | EPOLLOUT);
            if (revents & EPOLLHUP)
                revents |= (EPOLLIN | EPOLLOUT);

            // 处理读事件
            if (revents & EPOLLIN)
            {
                LOG(DEBUG, "fd-%d 读事件就绪\n", fd);
                if (isConnectionExisted(fd) && _connections[fd]->_handler_receiver)
                {
                    LOG(DEBUG, "fd-%d 处理读事件\n", fd);
                    _connections[fd]->_handler_receiver(_connections[fd]);
                }
                LOG(DEBUG, "fd-%d 处理读事件完毕\n", fd);
            }
            // 处理写事件
            if (revents & EPOLLOUT)
            {
                LOG(DEBUG, "处理写事件\n");
                if (isConnectionExisted(fd) && _connections[fd]->_handler_sender)
                    _connections[fd]->_handler_sender(_connections[fd]);
            }
        }
    }
    void Dispatcher()
    {
        _isRunning = true;
        int timeout = -1; // epoll阻塞等待
        while (_isRunning)
        {
            LoopOnce(timeout);
        }
        _isRunning = false;
    }

    bool isConnectionExisted(int fd)
    {
        return _connections.find(fd) != _connections.end();
    }

    void SetOnConnect(handler_t OnConnect)
    {
        _OnConnect = OnConnect;

    }

    void SetOnNormalHandler(handler_t receiver, handler_t sender, handler_t excepter)
    {
        _OnReceiver = receiver;
        _OnSender = sender;
        _OnExcepter = excepter;
    }

    void EableConnectionReadOrWrite(int fd, bool read_able, bool write_able)
    {
        if (!isConnectionExisted(fd))
            return;
        
        // 修改Connection要关心的事件
        uint32_t ev = ((read_able ? EPOLLIN : 0) | (write_able ? EPOLLOUT : 0) | EPOLLET);
        _connections[fd]->SetEvent(ev);

        // 写入到内核
        _epoller->ModEvent(fd, ev);
    }

    void DelConnection(int fd)
    {
        if (!isConnectionExisted(fd))
            return;

        LOG(INFO, "sockfd %d quit, 服务器释放所有资源\n", fd);
        // 1.在 epoller 中关闭对fd及其事件的关心
        _epoller->DelEvent(fd);

        // 2.关闭 sockfd
        _connections[fd]->Close();

        // 3.在_con中删除对连接的关心
        delete _connections[fd];
        _connections.erase(fd);
    }
private:
    std::unordered_map<int, Connection *> _connections; // 管理连接 fd-连接，通过fd可以检索到相应连接
    std::unique_ptr<Mutiplexing> _epoller;              // 封装 epoll 模型
    bool _isRunning;
    struct epoll_event _revs[gnum]; // 就绪事件缓冲区

    // 在reactor中记录处理Connection的方法集
    // 处理新连接到来
    handler_t _OnConnect;
    // 处理普通连接
    handler_t _OnReceiver;
    handler_t _OnSender;
    handler_t _OnExcepter;
};